﻿// -----------------------------------------------------------------------
// <copyright file="AcaoServico.cs" company="Storytelling">
// TODO: Update copyright text.
// </copyright>
// -----------------------------------------------------------------------

using System;
using System.Collections.Generic;
using System.Data.Entity;
using System.Text;

namespace Storytelling.Negocio
{
    using System.Linq;
    using System.Data.Objects;
    using Storytelling.Entidades;
    using Storytelling.Modelos;
    using Storytelling.Utils;
    using Storytelling.Entidades.VTR;

    public class AcaoServico : BaseServico<Acao, AcaoFormModel>
    {
        protected override void PreOperacao(ObjectContext context, AcaoFormModel model)
        {
            ObjectSet<Acao> objectSet = context.CreateObjectSet<Acao>();

            if (model.PoderValor.HasValue && model.PoderValor.Value != 0)
            {
                AcaoDisciplina acaoDisciplina = new AcaoDisciplina();
                acaoDisciplina.Id = model.Entidade.Id;
                acaoDisciplina.Atributo = model.Entidade.Atributo;
                acaoDisciplina.Campo = model.Entidade.Campo;
                acaoDisciplina.Descricao = model.Entidade.Descricao;
                acaoDisciplina.Inativado = model.Entidade.Inativado;
                acaoDisciplina.Modificador = model.Entidade.Modificador;
                acaoDisciplina.Nome = model.Entidade.Nome;
                acaoDisciplina.SinalModificador = model.Entidade.SinalModificador;

                acaoDisciplina.DisciplinaId = model.PoderValor;

                if (model.Entidade.Id != 0 && !objectSet.OfType<AcaoDisciplina>().Any(ent => ent.Id == model.Entidade.Id))
                {
                    objectSet.Attach(model.Entidade);
                    objectSet.DeleteObject(model.Entidade);
                    acaoDisciplina.Id = 0;
                }

                model.Entidade = acaoDisciplina;
            }
            else if (model.Entidade.Id != 0 && objectSet.OfType<AcaoDisciplina>().Any(ent => ent.Id == model.Entidade.Id))
            {
                AcaoDisciplina acaoDisciplina = new AcaoDisciplina();
                acaoDisciplina.Id = model.Entidade.Id;
                objectSet.Attach(acaoDisciplina);
                objectSet.DeleteObject(acaoDisciplina);
                model.Entidade.Id = 0;
            }
        }

        public override void Consultar(AcaoFormModel model, long id, Carga<Acao> carga)
        {
            using (var context = Context)
            {
                ObjectQuery<Acao> objectQuery = context.CreateObjectSet<Acao>();

                foreach (var item in carga)
                {
                    objectQuery = objectQuery.Include(item);
                }

                model.Entidade = objectQuery.Single(ent => ent.Id == id);

                AcaoDisciplina acaoDisciplina = model.Entidade as AcaoDisciplina;

                if (acaoDisciplina != null)
                {
                    model.Poder = acaoDisciplina.Disciplina.Nome;
                    model.PoderValor = acaoDisciplina.DisciplinaId.Value;
                }
            }
        }

        protected override void FiltrarCarregar(ObjectQuery<Acao> objectQuery)
        {
            objectQuery.OfType<AcaoDisciplina>().Include("Disciplina").Load();
        }

        public bool ParadaDados(long idPersonagem, long idAcao, long idArma, out int totalParada)
        {
            try
            {
                using (var context = Context)
                {
                    Acao acao = context.CreateObjectSet<Acao>().Single(ent => ent.Id == idAcao);

                    int penalidade = 0;

                    switch (acao.Campo.Value)
                    {
                        case Campo.Armamento:
                        case Campo.ArmasDeFogo:
                        case Campo.Briga:
                        case Campo.Conducao:
                        case Campo.Dissimulacao:
                        case Campo.Esportes:
                        case Campo.Furto:
                        case Campo.Sobrevivencia:
                        case Campo.Astucia:
                        case Campo.Empatia:
                        case Campo.Expressao:
                        case Campo.Intimidacao:
                        case Campo.Manha:
                        case Campo.Persuasao:
                        case Campo.Socializacao:
                        case Campo.TratoAnimais:
                            penalidade = -1;
                            break;
                        case Campo.Ciencias:
                        case Campo.Erudicao:
                        case Campo.Informatica:
                        case Campo.Investigacao:
                        case Campo.Medicina:
                        case Campo.Ocultismo:
                        case Campo.Oficios:
                        case Campo.Politica:
                            penalidade = -3;
                            break;
                    }

                    StringBuilder query = new StringBuilder();

                    IList<ObjectParameter> parametros = new List<ObjectParameter>();

                    parametros.Add(new ObjectParameter("idPersonagem", idPersonagem));

                    query.Append("SELECT VALUE (hum.");

                    query.Append(acao.Atributo);

                    query.Append(" + hum.");

                    query.Append(acao.Campo);

                    if (idArma > 0)
                    {
                        query.Append(" + arm.Dano");
                    }

                    AcaoDisciplina acaoDisciplina = acao as AcaoDisciplina;

                    if (acaoDisciplina != null)
                    {
                        query.Append(" + vpd.Nivel");
                    }

                    query.Append(" + (CASE WHEN hum.");

                    query.Append(acao.Campo);

                    query.Append(" = 0 THEN ");

                    query.Append(penalidade);

                    query.Append(" ELSE 0 END)) FROM Humano AS hum");

                    if (idArma > 0)
                    {
                        query.Append(" INNER JOIN HumanoArma AS har ON hum.Id = har.HumanoId INNER JOIN Arma AS arm ON arm.Id = har.ArmaId");
                    }                    
                    
                    if (acaoDisciplina != null)
                    {
                        query.Append(" INNER JOIN VampiroDisciplina AS vpd ON hum.Id = vpd.VampiroId");
                    }

                    query.Append(" WHERE hum.Id = @idPersonagem");

                    if (idArma > 0)
                    {
                        query.Append(" and har.Id = @idArma");
                        parametros.Add(new ObjectParameter("idArma", idArma));
                    }                    
                    
                    if (acaoDisciplina != null)
                    {
                        query.Append(" and vpd.DisciplinaId = @idDisciplina");
                        parametros.Add(new ObjectParameter("idDisciplina", acaoDisciplina.DisciplinaId));
                    }

                    totalParada = context.CreateQuery<int>(query.ToString(), parametros.ToArray())
                        .Execute(MergeOption.NoTracking).Single() + (acao.SinalModificador ? acao.Modificador : -(acao.Modificador));

                    return true;
                }
            }
            catch (Exception)
            {
                totalParada = 0;
                return false;
            }
        }
    }
}
